package controller;

import javafx.event.ActionEvent;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import model.ObjectLock;
import model.SharedObject;
import task.*;
import threadPool.MyThreadPoolExecutor;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

/**
 * @author wxhntmy
 */
public class TestThreadPoolController {

    /**
     * 创建新线程按键
     */
    public Button createNewThreadBtn;

    /**
     * 在线程里更新UI按键
     */
    public Button refreshUIOnThreadBtn;

    /**
     * Label
     */
    public Label UIDisplayLabel;

    /**
     * 创建新线程按键（带返回结果）
     */
    public Button createNewThreadBtnCallBack;

    /**
     * 创建新线程按键（带返回结果）返回Callable
     */
    public Button createNewThreadBtnCallBackCallable;

    /**
     * 关闭线程池
     */
    public Button closeThreadPoolBtn;

    /**
     * 关闭线程池（立即）
     */
    public Button closeThreadPoolNowBtn;

    /**
     * 对象锁
     */
    public Button objectLockBtn;

    /**
     * 线程池
     */
    private MyThreadPoolExecutor myThreadPoolExecutor = new MyThreadPoolExecutor();

    /**
     * 线程池实例
     */
    ExecutorService executorService = myThreadPoolExecutor.createNewThreadPool();

    /**
     * 创建新线程
     * @param actionEvent 事件
     */
    public void createNewThreadEvent(ActionEvent actionEvent) {
        MyTask myTask = new MyTask("new thread");
        //execute(Runnable)
        //这个方法接收一个Runnable实例，并且异步的执行
        if (executorService.isShutdown()) {
            executorService = myThreadPoolExecutor.createNewThreadPool();
        }
        executorService.execute(myTask);
    }

    /**
     * 在线程里更新UI
     * @param actionEvent 事件
     */
    public void refreshUIOnThreadEvent(ActionEvent actionEvent) {
        SharedObject sharedObject = new SharedObject();
        sharedObject.setUIDisplayLabel(UIDisplayLabel);
        //传递的参数是按引用进行传递，传递的是引用的地址，也就是变量所对应的内存空间的地址。
        RefreshUITask refreshUITask = new RefreshUITask("refresh UI Task", sharedObject);
        if (executorService.isShutdown()) {
            executorService = myThreadPoolExecutor.createNewThreadPool();
        }

        //execute(Runnable)
        //这个方法接收一个Runnable实例，并且异步的执行
        executorService.execute(refreshUITask);
    }

    /**
     * 创建新线程按键（带返回结果）
     * @param actionEvent 事件
     */
    public void createNewThreadBtnCallBackEvent(ActionEvent actionEvent) {
        ReturnResultTask returnResultTask = new ReturnResultTask("return result task");
        if (executorService.isShutdown()) {
            executorService = myThreadPoolExecutor.createNewThreadPool();
        }
        //submit(Runnable)可以返回一个Future对象，通过返回的Future对象，可以检查提交的任务是否执行完毕
        Future future = executorService.submit(returnResultTask);
        //如果任务执行完成，future.get()方法会返回一个null。注意，future.get()方法会产生阻塞。
        try {
            System.out.println("future.get(): " + future.get());
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建新线程按键（带返回结果）返回一个Callable
     * @param actionEvent 事件
     */
    public void createNewThreadBtnCallBackCallableEvent(ActionEvent actionEvent) {
        ReturnResultTaskCallable returnResultTaskCallable = new ReturnResultTaskCallable("return result callable");
        if (executorService.isShutdown()) {
            executorService = myThreadPoolExecutor.createNewThreadPool();
        }
        //submit(Callable)会返回一个Future对象，submit(Callable)接收的是一个Callable的实现，
        //Callable接口中的call()方法有一个返回值，可以返回任务的执行结果，而Runnable接口中的run()方法是void的，没有返回值。
        Future<Object> future = executorService.submit(returnResultTaskCallable);
        //如果任务执行完成，future.get()方法会返回Callable任务的执行结果。
        //注意，future.get()方法会产生阻塞。
        try {
            System.out.println("future.get(): " + future.get());
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }

    /**
     * 关闭线程池
     * @param actionEvent 事件
     */
    public void closeThreadPoolEvent(ActionEvent actionEvent) {
        //如果要关闭ExecutorService中执行的线程，可以调用ExecutorService.shutdown()方法。
        //在调用shutdown()方法之后，ExecutorService不会立即关闭，
        // 但是它不再接收新的任务，直到当前所有线程执行完成才会关闭，
        // 所有在shutdown()执行之前提交的任务都会被执行。

        if (!executorService.isShutdown()){
            System.out.println("ExecutorService Shutdown");
            executorService.shutdown();
        }

    }

    /**
     * 关闭线程池（立即）
     * @param actionEvent 事件
     */
    public void closeThreadPoolNowEvent(ActionEvent actionEvent) {
        //如果想立即关闭ExecutorService，可以调用ExecutorService.shutdownNow()方法。
        //这个动作将跳过所有正在执行的任务和被提交还没有执行的任务。
        //但是它并不对正在执行的任务做任何保证，有可能它们都会停止，也有可能执行完成。
        if (!executorService.isShutdown()) {
            System.out.println("ExecutorService Shutdown Now");
            executorService.shutdownNow();
        }
    }

    /**
     * 对象锁
     * @param actionEvent 事件
     */
    public void objectLockEvent(ActionEvent actionEvent) {

        ObjectLock objectLock = new ObjectLock();
        objectLock.setCounter(0);

        for (int i = 1; i < 9; i++) {
            ObjectLockTask objectLockTask = new ObjectLockTask("object lock task " + i, objectLock);
            executorService.execute(objectLockTask);
        }
        //objectLock.setCounter(objectLock.getCounter() + 1);
        //System.out.println("JavaFX Main Thread counter: " + objectLock.getCounter());

    }
}
